package main;

import java.util.ArrayList;
import java.util.List;
import java.util.Vector;

import boosting.AdaBoost;
import utils.DataManipulation;
import weka.classifiers.Classifier;
import weka.core.Instances;
import weka.filters.unsupervised.instance.Randomize;

public class MainBoosting {
	public static void main(String... args) {
		// argumentos
		// weakClassifier weka.classifiers.trees.J48 options -C 0.25 -M 2 dataset /home/andreybicalho/java_workspace/TP2_MachineLearning/iris.arff trainSplit 50 errorThreshold 0.95 iteracoes 5
		Vector classifierOptions = new Vector();
		String classifier = "";
		String dataset_path = "";
		
		Double error_threshold = 0.9;
	    double percentSplit = 50;
	    int iteracoes = 1;
	    
	    int i = 0;
		String current = "";
		boolean newPart = false; 
		do {
			// determine part of command line
			if (args[i].equals("weakClassifier")) {
				current = args[i];
				i++;
				newPart = true;
			} else if (args[i].equals("options")) {
				current = args[i];
				i++;
				newPart = true;
			} else if (args[i].equals("dataset")) {
				current = args[i];
				i++;
				newPart = true;
			} else if(args[i].equals("trainSplit")) {
				current = args[i];
				i++;
				newPart = true;
			}
			else if(args[i].equals("errorThreshold")) {
				current = args[i];
				i++;
				newPart = true;
			}
			else if(args[i].equals("iteracoes")) {
				current = args[i];
				i++;
				newPart = true;
			}

			
			
			
			if (current.equals("weakClassifier")) {
				if (newPart)
					classifier = args[i];
				else
					classifierOptions.add(args[i]);
			}
			else if(current.equals("options")){
					classifierOptions.add(args[i]);
			}
			else if (current.equals("dataset")) {
				if (newPart)
					dataset_path = args[i];
			}
			else if (current.equals("trainSplit")) {
				if(newPart)
					percentSplit = Integer.parseInt(args[i]);
			}
			else if (current.equals("errorThreshold")) {
				if(newPart)
					error_threshold = Double.parseDouble(args[i]);
			}
			else if (current.equals("iteracoes")) {
				if(newPart)
					iteracoes = Integer.parseInt(args[i]);
			}

			// next parameter
			i++;
			newPart = false;
		} while (i < args.length);
	    		
		String[] options = (String[])classifierOptions.toArray(new String[classifierOptions.size()]); 
		


		List<Double> acuracia = new ArrayList<Double>();

		// load data
		DataManipulation dataManipulation = new DataManipulation(dataset_path,
				"arff");

		int trainSize = (int) (dataManipulation.getDataset().numInstances()
				* percentSplit / 100);
		int testSize = dataManipulation.getDataset().numInstances() - trainSize;
		
		Instances dataset = new Instances(dataManipulation.getDataset(), 0, dataManipulation.getDataset().numInstances());
		
		
		for(int iter=0; iter < iteracoes;iter++){
		Instances trainSet = new Instances(dataset, 0, trainSize);
		
		// boosting process
		AdaBoost boosting = null;
		try {
			boosting = new AdaBoost(Classifier.forName(classifier,options),trainSet, dataset.numClasses(), error_threshold);
		
		} catch (Exception e) {
			// TODO Auto-generated catch block
			System.out.println("error while creating boosting object on: MainBoosting()");
			e.printStackTrace();
		}
		//
		boosting.buildAdaBoost();
		
		
		
		// testing boosting
		int numCorrect = 0;
		for(int n=trainSize;n < dataset.numInstances();n++){
			
			int pred = boosting.classifyInstance(dataset.instance(n));
			
			if(pred == dataset.instance(n).classValue())
				numCorrect++;
			
		}
		acuracia.add((double) numCorrect / (double) testSize * 100);
//		System.out.println("Acuracia: " + acuracia);
		
		
		// random flip on dataset
		Randomize randomize = new weka.filters.unsupervised.instance.Randomize();
		randomize.setRandomSeed(new java.util.Random().nextInt(99) + 1);
		weka.filters.Filter random = randomize;
		try {
			random.setInputFormat(dataset);
			dataset = weka.filters.Filter.useFilter(dataset,random);
		} catch (Exception e) {
			// TODO Auto-generated catch block
			System.out.println("error while random 'flip' on: MainBoosting");
			e.printStackTrace();
		}
	}
		
		
		// salva
		Double media = new Double(dataManipulation.getMean(acuracia));
		Double stdDev = new Double(dataManipulation.getStdDev(acuracia));
		String pathFile = "meta_" + classifier + "_boosting.txt";
		dataManipulation.save_to_file(media, stdDev, pathFile);
		
		
	}

}
